/*****	
	@file core.cpp
	@brief testing file
*/
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include "tests.h"
#include "Expr.h"
#include "functions.h"

using namespace sympycpp;
	  	  
void testOfTaylor(const int numberTest, const TestX & T) {
	int nT = 0;
	Expr x("x");
	Expr a("a");
	Expr b("b");
	Expr z(0);
	if (numberTest == ++nT || numberTest == 0) {
		Expr e(Sin(x));
		Expr s(e.taylorSeries(x, z, 10));
		T.test(s, "x-(1/6)x^3+(1/120)x^5-(1/5040)x^7+(1/362880)x^9", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e(Cos(x));
		Expr s(e.taylorSeries(x, 0, 10));
		T.test(s, "1-(1/2)x^2+(1/24)x^4-(1/720)x^6+(1/40320)x^8-(1/3628800)x^10", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e(Ln(x+1));
		Expr s(e.taylorSeries(x, z, 7));
		T.test(s, "x-(1/2)x^2+(1/3)x^3-(1/4)x^4+(1/5)x^5-(1/6)x^6+(1/7)x^7", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e(a^x);
		Expr s(e.taylorSeries(x, z, 5));
		T.test(s, "1+xLn(a)+(1/2)x^2Ln(a)^2+(1/6)x^3Ln(a)^3+(1/24)x^4Ln(a)^4+(1/120)x^5Ln(a)^5", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e(Ln((1+x)/(1-x)));
		Expr s(e.taylorSeries(x, 0, 7));
		T.test(s, "2x+(2/3)x^3+(2/5)x^5+(2/7)x^7", __LINE__, nT);
	}
} 
void testOfExpansion(const int numberTest, const TestX & T) {
	int nT = 0;
	Expr x("x");
	Expr a("a");
	Expr b("b");
	Expr c("c");
	Expr z(0);
	if (numberTest == ++nT || numberTest == 0) {
		Expr e(a*b*c*(2+c)*3*(a-b));
		e.expansion(-1);
		T.test(e, "-6ab^2c+6a^2bc-3ab^2c^2+3a^2bc^2", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a-b)*(b+a));
		e.expansion(-1);
		T.test(e, "a^2-(b^2)", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e(3*(a-b)*(b+a));
		e.expansion(-1);
		T.test(e, "3a^2-3b^2", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e(c*Sin((a-b)*(b-a)));
		e.expansion(-1);
		T.test(e, "cSin(-(a^2)-(b^2)+2ab)", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e(Cos(a*(b-c/a))*c*Sin((-a+b)*(b+a)));
		e.expansion(-1);
		T.test(e, "cCos(-c+ab)Sin(-(a^2)+b^2)", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a-b)*(-Ln(x)+Sin(x)));
		e.expansion(-1);
		T.test(e, "-aLn(x)+aSin(x)+bLn(x)-bSin(x)", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a-b)*(1/(a-b)+3/((a-b)^2)));
		e.expansion(-1);
		T.test(e, "1+3a/(a^2+b^2-2ab)-3b/(a^2+b^2-2ab)", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a-b)*(a*(a-b)+4*(a-b)));
		e.expansion(-1);
		T.test(e, "4a^2+a^3+4b^2-8ab+ab^2-2a^2b", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a-b)*(-Ln(x*(a+b))+Sin(x)));
		e.expansion(1); //  only 1 level is expanded
		T.test(e, "aSin(x)-bSin(x)-aLn(x(a+b))+bLn(x(a+b))", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a-b)*(-Ln(x*(a+b))+Sin(x)));
		e.expansion(-1); 
		T.test(e, "aSin(x)-bSin(x)-aLn(ax+bx)+bLn(ax+bx)", __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a+b)^2);
		e.expansion(-1); 
		T.test(e, ((a^2)+(b^2)+2*a*b).str(), __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a+b)^3);
		e.expansion(-1); 
		T.test(e, ((a^3)+(b^3)+3*(a^2)*b+3*(b^2)*a).str(), __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a-b)^3);
		e.expansion(-1); 
		T.test(e, ((a^3)-(b^3)-3*(a^2)*b+3*(b^2)*a).str(), __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a-b)^2);
		e.expansion(-1); 
		T.test(e, ((a^2)+(b^2)-2*a*b).str(), __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a+b+c)^2);
		e.expansion(-1); 
		T.test(e, ((a^2)+(b^2)+(c^2)+2*a*b+2*a*c+2*b*c).str(), __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a+b)^4);
		e.expansion(-1); 
		T.test(e, ((a^4)+(b^4)+4*(a^3)*b+4*(b^3)*a+6*(a^2)*(b^2)).str(), __LINE__, nT);
	}
	if (numberTest == ++nT || numberTest == 0) {
		Expr e((a+b-c)^3);
		e.expansion(-1); 
		T.test(e, (3*a*b*b-3*c*a*a-3*c*b*b+3*a*c*c+3*b*a*a+3*b*c*c+(a^3)+(b^3)-(c^3)-6*a*b*c).str(), __LINE__, nT);
	}
}
int main(){
	std::cout<<		"========================================"<<std::endl;
	TestX T(3);
	testOfTaylor(0, T);
	testOfExpansion(0, T);
	std::cout<<		"========================================"<<std::endl;
}
